package com.mf.common.dao.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import com.mf.common.dao.BaseDao;

@Repository
@Primary
public class BaseDaoImpl implements BaseDao {
	private static final Logger logger = LoggerFactory.getLogger(BaseDaoImpl.class);

	@Autowired
	protected SessionFactory sessionFactory;

	public void saveOrUpdate(Object transientInstance) {
		try {
			sessionFactory.getCurrentSession().saveOrUpdate(transientInstance);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void flush() {
		try {
			sessionFactory.getCurrentSession().flush();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public Serializable save(Object transientInstance) {
		Serializable id = null;
		try {
			id = sessionFactory.getCurrentSession().save(transientInstance);
		} catch (RuntimeException re) {
			throw re;
		}
		return id;
	}

	/*
	 * public Serializable save(BaseObject transientInstance, boolean flush) {
	 * Serializable id = null; try {
	 * sessionFactory.getCurrentSession().save(transientInstance);
	 * sessionFactory.getCurrentSession().flush(); id =
	 * transientInstance.getId(); } catch (RuntimeException re) { throw re; }
	 * return id; }
	 */

	public Serializable update(Object transientInstance) {
		Serializable id = null;
		try {
			sessionFactory.getCurrentSession().update(transientInstance);
			sessionFactory.getCurrentSession().flush();
		} catch (RuntimeException re) {
			throw re;
		}
		return id;
	}

	public void delete(Object persistentInstance) {
		try {
			sessionFactory.getCurrentSession().delete(persistentInstance);
			sessionFactory.getCurrentSession().flush();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void deleteAll(Class entityClass) {
		// try
		// {
		// sessionFactory.getCurrentSession().deleteAll(findAll(entityClass));
		// }
		// catch (RuntimeException re) {
		// throw re;
		// }
	}

	public void deleteAll(Collection entities) {
		// try
		// {
		// sessionFactory.getCurrentSession().deleteAll(entities);
		// }
		// catch (RuntimeException re) {
		// throw re;
		// }
	}

	public Object findById(Class entityClass, Serializable id) {
		try {
			return sessionFactory.getCurrentSession().get(entityClass, id);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByExample(Object instance) {
		try {
			Example exampleObject = Example.create(instance);
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(instance.getClass()).add(
					exampleObject);
			return criteria.list();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findAll(Class entityClass) {
		List list = null;
		try {
			list = sessionFactory.getCurrentSession().createQuery("from " + entityClass.getName()).list();
			return list;
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByProperty(Class entityClass, String propertyName, Object value) {
		List list = null;
		try {
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(entityClass);
			criteria.add(Restrictions.eq(propertyName, value));
			list = criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();

			return list;
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByProperties(Class entityClass, String[] propertyNames, Object[] values) {

		List list = null;
		try {
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(entityClass);

			for (int i = 0; i < propertyNames.length; i++) {
				criteria.add(Restrictions.eq(propertyNames[i], values[i]));
			}

			list = criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();

			return list;
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public Object findByPropertyUnique(Class entityClass, String propertyName, Object value) {
		try {
			return sessionFactory.getCurrentSession().createCriteria(entityClass).add(
					Restrictions.eq(propertyName, value)).uniqueResult();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByIds(Class claz, List<Serializable> idList) {
		List list = null;
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(claz);
		if (idList != null && idList.isEmpty() == false) {
			criteria.add(Restrictions.in("id", idList.toArray()));
			list = criteria.list();
		}
		return list;
	}

	public void evict(Object objToEvict) {
		sessionFactory.getCurrentSession().evict(objToEvict);
	}

	public void merge(Object obj) {
		sessionFactory.getCurrentSession().merge(obj);
	}

}